
/*=========== E-Bike inverter project ==================*/
#include "main.h"

unsigned char 			txBuffer[LCD_BUFFER_LEN];	
unsigned char 			rxBuffer[LCD_BUFFER_LEN];
unsigned int			dcCurrentOffset=0, torqueOffset=0;
unsigned char			cState=SM_IDLE;	
unsigned char			torqueFactor = 0;					// sets the torque to current factor which can be changed by the user
unsigned long			torqueOffsetFil;
unsigned int			lastCurDem=0;		
long 					energyCounter=0;
int						maxDemandCurrent;
long					torqueCurGain;


// ***************************************************************************************************************
// initialize ports 
// ***************************************************************************************************************
void initPorts(void)
{
	DDRB = HS_U|HS_V|HS_W|LS_W;		
	DDRC = LS_V;		
	DDRD = LS_U;

	DDR_LED|= LED;	

	PORT_SHDN&= ~SHDN;
	DDR_SHDN|= SHDN;
	
	DDR_BMS_VCC|= BMS_VCC;
	
	//inverter temperature
	DDR_TEMP&= ~PIN_TEMP;	
	
	//I2C
	DDR_I2C|= SDA|SCL;
	PORT_I2C&= ~(SDA|SCL);	
}


// ***************************************************************************************************************
// initialize ADC
// ***************************************************************************************************************
void initADC( void )
{
	ADCSRA = (1 << ADEN) | (1 << ADPS0) | (0 << ADPS1) | (1 << ADPS2); 	//Clockdiv = 32 -> 500kHz, Highspeed mode -> mehr geht nicht!
	ADCSRB = (1 << ADHSM);
	
	//remark: amplifier runs on 1/8 of ADC Clock + stable result after 4 conversions
	//set amplifier AMP0 gain = 5
	AMP0CSR = (1<<AMP0EN);	
	//wait for amplifier to settle
	delay_ms(1);

	//read offsets
	ADMUX= ADC_MUX_DISCHARGE_CURRENT | ADC_SETTINGS;
	ADCSRA|= (1 << ADSC);
	// Wait for ADC conversion to complete.
	while ( ADCSRA & (1 << ADSC) );
	dcCurrentOffset = ADCW;
		
	ADMUX= ADC_MUX_TORQUE_SENSOR | ADC_SETTINGS;
	ADCSRA|= (1 << ADSC);
	// Wait for ADC conversion to complete.
	while ( ADCSRA & (1 << ADSC) );
	torqueOffset = ADCW;
	torqueOffsetFil = torqueOffset << 3;
}

// ***************************************************************************************************************
// Read ADC 
// ***************************************************************************************************************
unsigned int readADC(unsigned char channel)
{
    ADMUX = channel | ADC_SETTINGS;
    // Start AD conversion.
    
	ADCSRA |= (1 << ADSC) ;
    // Wait for ADC conversion to complete.
    while ( ADCSRA & (1 << ADSC) );
    
	return ADCW;
}

// ***************************************************************************************************************
// Read TEMP (KTY81-110) 
// ***************************************************************************************************************
int readKTY81110(void)
{
	long resLong = 0;
	int	resShort = 0;
	int rawValue;
	rawValue = readADC(ADC_MUX_TEMP) - KTY81_OFFSET;
	
	resLong =   (long) rawValue * KTY81_GAIN;
    resShort =  (int)(resLong >> (15-SHIFT_TEMP));
	// shiftr 15: conversion 30bit to 15bit value
    // shfitl SHIFT_DC_CUR: we multiplied with normed value
	
	return resShort;  
}

// ***************************************************************************************************************
// read DC Current
// ***************************************************************************************************************
int readDCCurrent(void)
{
	long resLong = 0;
	int	resShort = 0;
	int rawValue;
	
	rawValue = readADC(ADC_MUX_DISCHARGE_CURRENT) - dcCurrentOffset;	
	
	resLong =   (long) rawValue * DISCHARGE_CUR_GAIN;
    resShort =  (int)(resLong >> (15-SHIFT_DC_CUR));
	// shiftr 15: conversion 30bit to 15bit value
    // shfitl SHIFT_DC_CUR: we multiplied with normed value 
	
	return resShort;

}

// ***************************************************************************************************************
// read DC Voltage
// ***************************************************************************************************************
int readDCVoltage(void)
{
	long resLong = 0;
	int	resShort = 0;
	int rawValue;
	
	rawValue = readADC(ADC_MUX_V_DC);	
	
	resLong =   (long) rawValue * DC_VOLTAGE_GAIN;
    resShort =  (int)(resLong >> (15-SHIFT_DC_VOLTAGE));
	// shiftr 15: conversion 30bit to 15bit value
    // shfitl SHIFT_DC_CUR: we multiplied with normed value  
	
	return resShort;

}



// ***************************************************************************************************************
// calulate the demand current from the torque sensor 
// ***************************************************************************************************************
int calcDemandCurrent(void)
{
	long resLong = 0;
	int	resShort = 0;
	
	//torqueOffset is recalculated during SM_IDLE
	int rawValue = readADC(ADC_MUX_TORQUE_SENSOR) - torqueOffset;
	// only positive values
	if (rawValue < 0) rawValue = 0;	
	
	resLong =   (long) rawValue * torqueCurGain;
    resShort =  (int)(resLong >> (15-SHIFT_DC_CUR));		
	// shiftr 15: conversion 30bit to 15bit value
    // shfitl SHIFT_DC_CUR: we multiplied with normed value
	
	//current limiter
	if (resShort > maxDemandCurrent) resShort = maxDemandCurrent;
	
	//ramp up and down
	if ((resShort > lastCurDem) && (resShort > (MIN_DEMAND_CUR+CUR_HYST)))
	{
		lastCurDem = resShort-CUR_HYST;
	}
	else 
	{
		//ramp down -> set by shift factor and Ts
		if (lastCurDem > DEM_CURRENT_DEC) lastCurDem-= DEM_CURRENT_DEC;
	}

	
	return lastCurDem;
}

void shutdown(void)
{
	cli();
	pscStop();
	
	char *ptr = (char*) &energyCounter;
	//write energy counter and settings to EEPROM
	for(int i=0;i<4;i++){
		eeprom_write_byte((unsigned char *) i+1,*ptr++);		//nicht an erster EEPROM Position sondern eins verschoben
	}
	eeprom_write_byte((unsigned char *) 5,torqueFactor);

	dsprintf((char *) txBuffer, " Goodbye...                      ");
	txBuffer[0] = 0xFF; //character mode

	spiMasterReadWrite(txBuffer,rxBuffer,LCD_BUFFER_LEN);

	wdt_reset();	
	wdt_disable();	
	while(1);
}


// ***************************************************************************************************************
// main routine
// ***************************************************************************************************************
int main (void){
	wdt_reset();	
	wdt_disable();	
	
	int demandCurrent=0;
	int dcCurrent=0;
	int avCurrent=0;
	int avCurrentDisp=0;
	unsigned int dcVoltage=0;
	unsigned int dcVoltageDisp=0;
	int invTemp=0;
	long integrator=0;
	int dcCurErr=0,dcVoltErr=0,err=0,err1=0,err2=0; 
	unsigned char i= 0;	
	unsigned char debounceCounter=0;
	unsigned int balCFG=0;
	unsigned int minCellVoltage;
	unsigned int maxCellVoltage;
	long curSum=0;
	unsigned int curSumCounter=0;
	int energyCounterDisp=0;
	
	
	
	//=======INIT==========
	//wait for system to settle and main switch to reach full gate charge
	delay_ms(2000);	
	
	
	//read energy counter and torque settings from EEPROM
	char *ptr = (char *) &energyCounter;
	for(int i=0;i<4;i++){
		*ptr++= eeprom_read_byte((unsigned char *) i+1);		//nicht an erster EEPROM Position sondern eins verschoben
	}	
	torqueFactor = eeprom_read_byte((unsigned char *) 5);
	if (torqueFactor == 0)
	{	 
		maxDemandCurrent = MAX_DEMAND_CURRENT0;
		torqueCurGain = TORQUE_CUR_GAIN0;
	}
	else if (torqueFactor == 1) 
	{
		maxDemandCurrent = MAX_DEMAND_CURRENT1;
		torqueCurGain = TORQUE_CUR_GAIN1;
	}
	else 
	{
		maxDemandCurrent = MAX_DEMAND_CURRENT2;
		torqueCurGain = TORQUE_CUR_GAIN2;
	}
	
	
	initPorts();	
	//init ADC and read offsets
	initADC();		
	spiMasterInit();	
	//redirect SPI to alternate ports (only AT90PWM3B)
	MCUCR|= (1<<SPIPS);	
	

	//initialize power stage controller, hall sensor interrupts and svpwm 
	hallSensorInit();
	pscInit(MAX_PWM);
	
	//BMS
	i2c_init();		
	
	//init motor (not running!)
	sei();			
	svpwmInit();	
				
	
	// =======main loop==========
		
	
	//init timers for dispatcher
	startClock();
	unsigned int controlTimer = setDelay_ms(Tms);
	unsigned int secondTimer = setDelay_ms(1000);
	unsigned int averageTimer = setDelay_ms(100);

	//enable Watchdog
	//wdt_enable(WDTO_250MS);

	while(1)
	{
		//reset watchdog
		//wdt_reset();
		
		if (checkDelay_ms(controlTimer))
		{
			controlTimer = setDelay_ms(Tms);	
			//read all (all the time, independet from state machine)
			dcCurrent = readDCCurrent();
			dcVoltage = readDCVoltage();
			demandCurrent = calcDemandCurrent();
			
			if (cState == SM_RIDING)
			{							
				//execute PI Controller
				err2 = err1;						//save error history
				err1 = err;
				
				//calculate errors
				err = 0x7FFF;
				dcCurErr = demandCurrent - dcCurrent;
				dcVoltErr =  dcVoltage - UNDER_VOLTAGE_LIMIT;	//decrease current in case of under-voltage

				if (dcCurErr < err) err = dcCurErr;		
				if (dcVoltErr < err) err = dcVoltErr;				

				integrator+= (long) err * K0 + (long) err1 * K1; //+ (long) err2 * K2;
				
				if (integrator > INT_MAX) integrator = INT_MAX;
				if (integrator < INT_MIN) integrator = INT_MIN;
				
				amplitude = integrator >> 16;	
			}
			else
			{
				//reset integrator & amplitude if state != SM_RIDING
				integrator = INT_MIN;
				amplitude = integrator >> 16;
			}
		}
		
		if (checkDelay_ms(averageTimer))
		{
			averageTimer = setDelay_ms(100);
			
			//sum current for average current and energy counter
			if (cState == SM_RIDING)
				curSum+= dcCurrent;
			else if (cState == SM_CHARGING) 
				//set constant charging current
				curSum-= CRG_CURRENT;
			else
				;//do nothing;
				
			curSumCounter++;
			
			//check dc voltage for shutdown condition
			if (dcVoltage < SHUTDOWN_VOLTAGE) shutdown();
		}
		
		
		if (checkDelay_ms(secondTimer))
		{
			secondTimer = setDelay_ms(1000);
			
			//update avaerage current and energy counter
			//curSom/curSumCount -> Average Current in one second -> then divide by seconds per hour -> Ah
			avCurrent = (long) curSum / curSumCounter; 
			energyCounter+= avCurrent;	//energy in As (normed by SHIFT_DC_CUR) -> divide by 3600 for Ah
			curSumCounter=0;
			curSum = 0;	
			if (energyCounter < 0) energyCounter = 0; //only positive values
			
			//update state machine
			switch (cState)
			{
				case SM_IDLE:
				{
					
					//check if riding
					if (calcDemandCurrent() > RIDING_TRESHOLD)
					{
						//start motor
						cState = SM_RIDING;
						pscStart();				
					}
					else	
					{
						//check if charger is connected 
						bmsEnable(TRUE); //enable BMS interface
						delay_ms(5);
						if (bmsReady()) cState = SM_CHARGING;
						else
						{
							//disable BMS interface again
							bmsEnable(FALSE);
											
							//reset the torque sensor offset (with PT1 filter)
							torqueOffsetFil = (((unsigned long) (torqueOffsetFil<<3) - torqueOffsetFil) + ((unsigned long) readADC(ADC_MUX_TORQUE_SENSOR)<<3)) >>3;
							torqueOffset = torqueOffsetFil>>3;	
							
							dcVoltageDisp = dcVoltage >> SHIFT_DC_VOLTAGE;						
							
							//update display
							energyCounterDisp = (long) (energyCounter>>SHIFT_DC_CUR)*9 >> 15;			//divide by 1/3600, ~= multiply with 9 and >> 15 
							invTemp = readKTY81110() >> SHIFT_TEMP;
							
							//use character mode (first char = 0xFF) and print 2 formatted lines (2x16) on display
							dsprintf((char *) txBuffer, " Idle %2u,%1u V %2u CF%1u OS: %4u %2u,%1u", dcVoltageDisp/10, dcVoltageDisp%10, invTemp, torqueFactor, torqueOffset, energyCounterDisp/10, energyCounterDisp%10);
							txBuffer[0] = 0xFF; //character mode

							spiMasterReadWrite(txBuffer,rxBuffer,LCD_BUFFER_LEN);

							//check buttons
							if ((rxBuffer[0] & 0x03) == 0x03) //button1&2 pressed
							{
								cState = SM_RESET; //switch to RESET STATE
							}
							else
							{
								if (rxBuffer[0] & 0x01)	//button1 pressed
								{
									//charge torque to current ratio
									if (torqueFactor < MAX_TORQUE_FACTOR) torqueFactor++;
									else torqueFactor = 0;
									
									if (torqueFactor == 0)
									{	 
										maxDemandCurrent = MAX_DEMAND_CURRENT0;
										torqueCurGain = TORQUE_CUR_GAIN0;
									}
									else if (torqueFactor == 1) 
									{
										maxDemandCurrent = MAX_DEMAND_CURRENT1;
										torqueCurGain = TORQUE_CUR_GAIN1;
									}
									else 
									{
										maxDemandCurrent = MAX_DEMAND_CURRENT2;
										torqueCurGain = TORQUE_CUR_GAIN2;
									}
								}							
								if (rxBuffer[0] & 0x02)	//button2 pressed
								{
								}
							}
							
						}	
					}
					
					break;
					
				}	

				case SM_RESET:
				{
					//reset energyCounter
					energyCounter = 0;					
					
					cState = SM_IDLE; //switch to IDLE STATE
					
					break;
				}
				
				case SM_RIDING:
				{
					//update display
					//take last measurement from control timer and shift it for display
					demandCurrent = demandCurrent >> SHIFT_DC_CUR;
					avCurrentDisp = avCurrent >> SHIFT_DC_CUR;
					dcVoltageDisp = dcVoltage >> SHIFT_DC_VOLTAGE;
					invTemp = readKTY81110() >> SHIFT_TEMP;

					txBuffer[0] = 0; 				//layout
					txBuffer[2] = rpm;				//rpm
					txBuffer[3] = rpm >> 8;
					txBuffer[4] = dcVoltageDisp; 	//Voltage 
					txBuffer[5] = dcVoltageDisp >> 8;
					txBuffer[6] = avCurrentDisp; 	//current 
					txBuffer[7] = avCurrentDisp >> 8;
					
					txBuffer[8] = invTemp;		//temperature
					txBuffer[9] = invTemp >> 8;
					
					spiMasterReadWrite(txBuffer,rxBuffer,10);				
					
					//check if standing
					if ((rpm < RPM_TRESHOLD) && (debounceCounter < STANDING_DELAY))  debounceCounter++;
					else debounceCounter = 0;
					
					//if standing for >= STANDING_DELAY seconds, goto SM_IDLE 
					if (debounceCounter >= STANDING_DELAY)
					{
						pscStop();
						//reset torque offset
						torqueOffsetFil = (unsigned long) readADC(ADC_MUX_TORQUE_SENSOR)<<3;
						torqueOffset = torqueOffsetFil>>3;	
						
						cState = SM_IDLE;
					}
					break;	
				}
				
				case SM_CHARGING:
				{
					if (bmsReady()){						
						//disable balancing during measurement						
						bmsBalanceCell(0,0);
						bmsReadAll();
						//balance all
						balCFG = bmsBalanceAll(BALANCE_TRESHOLD,MAX_CELL_VOLTAGE, 15);			
						
						dcVoltageDisp = 0;
						minCellVoltage = MAX_CELL_VOLTAGE;
						maxCellVoltage = 0;
						for(i=0;i<12;i++)
						{
							dcVoltageDisp+= (cellVoltage[i] >> SHIFT_BMS_VOLTAGE) / 10;	
							if (cellVoltage[i] < minCellVoltage) minCellVoltage = cellVoltage[i];							
							if (cellVoltage[i] > maxCellVoltage) maxCellVoltage = cellVoltage[i];
						}		
						
						//convert to display
						dcVoltageDisp = dcVoltageDisp / 10 ;						//display in 0.1V
						minCellVoltage = minCellVoltage >> SHIFT_BMS_VOLTAGE;
						maxCellVoltage = maxCellVoltage >> SHIFT_BMS_VOLTAGE;
						
						dsprintf((char *) txBuffer, " %2u,%1u V %4u %4u    %12b", dcVoltageDisp/10, dcVoltageDisp%10, minCellVoltage, maxCellVoltage, balCFG);
						txBuffer[0] = 0xFF; //character mode
						spiMasterReadWrite(txBuffer,rxBuffer,LCD_BUFFER_LEN);
						
						//check if maximum voltage is reached for MAX_VOLTAGE_DEBOUNCE seconds
						if ((dcVoltageDisp > MAX_VOLTAGE) && (debounceCounter < MAX_VOLTAGE_DEBOUNCE)) debounceCounter++;
						else debounceCounter = 0;
						
						if (debounceCounter >= MAX_VOLTAGE_DEBOUNCE) cState = SM_CHARGE_FINISHED;
						else bmsSetChargeEnable(TRUE);	//enable charger switch
						
						//reset energy counter
						if (dcVoltageDisp > CRG_FULL_VOLTAGE) energyCounter = 0;							
					}	
					else
					{
						//charger disconnected during charging
						cState = SM_IDLE;
						//reset torque offset
						torqueOffsetFil = (unsigned long) readADC(ADC_MUX_TORQUE_SENSOR)<<3;
						torqueOffset = torqueOffsetFil>>3;	
						
						bmsEnable(FALSE);
					}						
					break;	
				}
				
				case SM_CHARGE_FINISHED:
				{
					if (bmsReady()){
						//turn of charger switch, just display values
						bmsSetChargeEnable(FALSE);
						//dcVoltageDisp = dcVoltage >> SHIFT_DC_VOLTAGE;						
						//dsprintf((char *) txBuffer, " %2u,%1u V          Finished    ", dcVoltageDisp/10, dcVoltageDisp%10);
						//txBuffer[0] = 0xFF; //character mode
						//spiMasterReadWrite(txBuffer,rxBuffer,LCD_BUFFER_LEN);
					}
					else
					{
						//charger disconnected during charging
						cState = SM_IDLE;
						//reset torque offset
						torqueOffsetFil = (unsigned long) readADC(ADC_MUX_TORQUE_SENSOR)<<3;
						torqueOffset = torqueOffsetFil>>3;	
						
						bmsEnable(FALSE);
					}					
					break;	
				}
			}		
		}
	}
	
	
}




// ============================== BACKUP ====================================0

	/*	
	//BMS Test
	bmsEnable(TRUE);
	delay_ms(1000);		
	i2c_init();
	unsigned char i= 0;	
	unsigned int balCFG=0;
	
	//enable charging
	bmsSetChargeEnable(TRUE);	
	
	while(1)
	{		
		
		if (bmsReady()){	
			//disable balancing during measurement
			bmsBalanceCell(0,0);
			bmsReadAll();
			//balance all
			balCFG = bmsBalanceAll(30<<SHIFT_BMS_VOLTAGE,4200<<SHIFT_BMS_VOLTAGE, 15);			
			
			txBuffer[3] = (unsigned char) (balCFG & 0xFF);
			txBuffer[4] = (unsigned char) ((balCFG >> 8) & 0xFF);	
			
			for (i=1;i<=12;i++){	
				
				txBuffer[0] = (unsigned char) ((cellVoltage[i]>>SHIFT_BMS_VOLTAGE) & 0xFF);		
				txBuffer[1] = (unsigned char) (((cellVoltage[i]>>SHIFT_BMS_VOLTAGE) >> 8) & 0xFF);
				txBuffer[2] = i;
				
				spiMasterReadWrite(txBuffer,rxBuffer,5);
				PORT_LED^=LED;
				delay_ms(1000);
			}			
		}	
		delay_ms(1000);		
	}
	
	
	
	
	
	
	//Generiert selbst die Hall Signale im 1ms Takt
	DDRB|= (1<<2)|(1<<5);
	DDRD|= (1<<6);
	unsigned char has;
	while(1)
	{
		has = HAS1;
		if (has & (1<<0)) PORTB|= (1<<2);
		else PORTB&= ~(1<<2);
		if (has & (1<<1)) PORTD|= (1<<6);
		else PORTD&= ~(1<<6);
		if (has & (1<<2)) PORTB|= (1<<5);
		else PORTB&= ~(1<<5);
		delay_ms(10);
		has = HAS2;
		if (has & (1<<0)) PORTB|= (1<<2);
		else PORTB&= ~(1<<2);
		if (has & (1<<1)) PORTD|= (1<<6);
		else PORTD&= ~(1<<6);
		if (has & (1<<2)) PORTB|= (1<<5);
		else PORTB&= ~(1<<5);
		delay_ms(10);
		has = HAS3;
		if (has & (1<<0)) PORTB|= (1<<2);
		else PORTB&= ~(1<<2);
		if (has & (1<<1)) PORTD|= (1<<6);
		else PORTD&= ~(1<<6);
		if (has & (1<<2)) PORTB|= (1<<5);
		else PORTB&= ~(1<<5);
		delay_ms(10);
		has = HAS4;
		if (has & (1<<0)) PORTB|= (1<<2);
		else PORTB&= ~(1<<2);
		if (has & (1<<1)) PORTD|= (1<<6);
		else PORTD&= ~(1<<6);
		if (has & (1<<2)) PORTB|= (1<<5);
		else PORTB&= ~(1<<5);
		delay_ms(10);
		has = HAS5;
		if (has & (1<<0)) PORTB|= (1<<2);
		else PORTB&= ~(1<<2);
		if (has & (1<<1)) PORTD|= (1<<6);
		else PORTD&= ~(1<<6);
		if (has & (1<<2)) PORTB|= (1<<5);
		else PORTB&= ~(1<<5);
		delay_ms(10);
		has = HAS6;
		if (has & (1<<0)) PORTB|= (1<<2);
		else PORTB&= ~(1<<2);
		if (has & (1<<1)) PORTD|= (1<<6);
		else PORTD&= ~(1<<6);
		if (has & (1<<2)) PORTB|= (1<<5);
		else PORTB&= ~(1<<5);
		delay_ms(10);
		
		amplitude = readADC(ADC_MUX_TORQUE_SENSOR);
		txBuffer[0] = (unsigned char) amplitude;
		txBuffer[1] = amplitude>>8;
		//txBuffer[2] = dischargeCurrent;
		txBuffer[3] = amplitude;
		spiMasterReadWrite(txBuffer,rxBuffer,4);
	}
	
	
	*/

	
	/*
	//Motor test
	unsigned int pwm = 70;
	unsigned int delay = 2000;	
	while(1){
		PCTL2 = (1<<PCCYC2);
		pscLoad(pwm, 0, 0);
		PORTD|= LS_U;			
		PORTC|= LS_V;		
		PORTB&= ~LS_W;
		PCTL2 = (1<<PCCYC2) | (1<<PRUN2);	
		delay_ms(delay);
		txBuffer[0] = HALL_A_MASK | HALL_B_MASK | HALL_C_MASK;
		txBuffer[1] = 2;
		spiMasterReadWrite(txBuffer,rxBuffer,2);
		
		PCTL2 = (1<<PCCYC2);
		PORTD|= LS_U;			
		PORTC&= ~LS_V;		
		PORTB|= LS_W;
		PCTL2 = (1<<PCCYC2) | (1<<PRUN2);
		delay_ms(delay);
		txBuffer[0] = HALL_A_MASK | HALL_B_MASK | HALL_C_MASK;
		txBuffer[1] = 6;
		spiMasterReadWrite(txBuffer,rxBuffer,2);
		
		PCTL2 = (1<<PCCYC2);
		pscLoad(0, pwm, 0);
		PORTD&= ~LS_U;			
		PORTC|= LS_V;		
		PORTB|= LS_W;	
		PCTL2 = (1<<PCCYC2) | (1<<PRUN2);
		delay_ms(delay);
		txBuffer[0] = HALL_A_MASK | HALL_B_MASK | HALL_C_MASK;
		txBuffer[1] = 4;
		spiMasterReadWrite(txBuffer,rxBuffer,2);
		
		PCTL2 = (1<<PCCYC2);
		PORTD|= LS_U;			
		PORTC|= LS_V;		
		PORTB&= ~LS_W;
		PCTL2 = (1<<PCCYC2) | (1<<PRUN2);
		delay_ms(delay);
		txBuffer[0] = HALL_A_MASK | HALL_B_MASK | HALL_C_MASK;
		txBuffer[1] = 5;
		spiMasterReadWrite(txBuffer,rxBuffer,2);
		
		PCTL2 = (1<<PCCYC2);
		pscLoad(0, 0, pwm);
		PORTD|= LS_U;			
		PORTC&= ~LS_V;		
		PORTB|= LS_W;	
		PCTL2 = (1<<PCCYC2) | (1<<PRUN2);
		delay_ms(delay);
		txBuffer[0] = HALL_A_MASK | HALL_B_MASK | HALL_C_MASK;
		txBuffer[1] = 1;
		spiMasterReadWrite(txBuffer,rxBuffer,2);
		
		PCTL2 = (1<<PCCYC2);
		PORTD&= ~LS_U;			
		PORTC|= LS_V;		
		PORTB|= LS_W;
		PCTL2 = (1<<PCCYC2) | (1<<PRUN2);
		delay_ms(delay);
		txBuffer[0] = HALL_A_MASK | HALL_B_MASK | HALL_C_MASK;
		txBuffer[1] = 3;
		spiMasterReadWrite(txBuffer,rxBuffer,2);
	}
	*/
